home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / gsdbloo.exe / GS_SORT.PAS < prev    next >
Pascal/Delphi Source File  |  1992-02-24  |  6KB  |  211 lines

  1. unit GS_Sort;
  2. {-----------------------------------------------------------------------------
  3.                            Keyboard Input Routines
  4.  
  5.        GS_Sort Copyright (c)  Richard F. Griffin
  6.  
  7.         1 January 1991
  8.  
  9.        102 Molded Stone Pl
  10.        Warner Robins, GA  31088
  11.  
  12.        -------------------------------------------------------------
  13.        This unit handles the objects for sorting lists.
  14.  
  15.    Changes:
  16.  
  17. ------------------------------------------------------------------------------}
  18.  
  19. interface
  20. {$D-}
  21.  
  22. type
  23.    GS_Sort_Objt = object
  24.        Ascending   : boolean;
  25.        Gt_Sign,
  26.        Lt_Sign     : integer;
  27.        constructor InitSort(ascnd : boolean);
  28.        procedure   SortDir(ascnd : boolean);
  29.        procedure   Sort(var tabl; clth : word; icnt : longint);
  30.        function    Search(key : string; var tabl; clth : word;
  31.                                 icnt : longint) : longint;
  32.        function    Compare(var s1, s2) : integer; virtual;
  33.     end;
  34.  
  35. function GS_Sort_Compare(var s1,s2) : integer;
  36. procedure GS_Sort_Swap(var s1,s2; len : word);
  37.  
  38. implementation
  39.  
  40. type
  41.    buf_type         = array[0..0] of byte;
  42.  
  43. var
  44.    buffer           : ^buf_type;
  45.    reclen           : word;             { record length }
  46.  
  47. function GS_Sort_Compare(var s1,s2) : integer;
  48. var
  49.    st1 : string absolute s1;
  50.    st2 : string absolute s2;
  51.    flg : integer;
  52.    eql : boolean;
  53. begin
  54.    eql := st1 = st2;
  55.    Inline(              {Get flag register in flg}
  56.      $9C/                   {  PUSHF           ;Push flag register}
  57.      $59/                   {  POP     CX      ;Get flag register in CX}
  58.      $89/$4E/<flg);         {  MOV     <flg,CX ;Store CX in flg}
  59.    if eql then GS_Sort_Compare := 0
  60.       else if (flg and $0080) = 0 then
  61.          GS_Sort_Compare := 1             {s1 > s2 if sign flag 0}
  62.             else GS_Sort_Compare := -1;   {s1 < s2 if sign flag 1}
  63. end;
  64.  
  65. procedure GS_Sort_Swap(var s1,s2; len : word);
  66. begin
  67.    inline(
  68.       $1E/          { push ds           ; save DS reg }
  69.       $8B/$8E/len/  { mov cx,[bp+4]     ; CX = len }
  70.       $C5/$B6/s1/   { lds si,[bp+10]    ; DS:SI = var s1 }
  71.       $C4/$BE/s2/   { les di,[bp+6]     ; ES:DI = var s2 }
  72.       $FC/          { cld               ; set forward direction }
  73.       $8A/$04/      { mov al,[SI]       ; get a }
  74.       $8A/$25/      { mov ah,[DI]       ; get b }
  75.       $88/$24/      { mov [SI],ah       ; store a }
  76.       $AA/          { stosb             ; store b }
  77.       $46/          { inc si            ; increment }
  78.       $E2/$F6/      { loop ...          ; continue }
  79.       $1F           { pop ds            ; restore DS reg }
  80.    );
  81. end;
  82.  
  83. constructor GS_Sort_Objt.InitSort(ascnd : boolean);
  84. begin
  85.    Ascending := ascnd;
  86.    if ascnd then
  87.    begin
  88.       Gt_Sign := 1;
  89.       Lt_Sign := -1;
  90.    end
  91.    else
  92.    begin
  93.       Gt_Sign := -1;
  94.       Lt_Sign := 1;
  95.    end;
  96. end;
  97.  
  98. procedure GS_Sort_Objt.SortDir(ascnd : boolean);
  99. begin
  100.    Ascending := ascnd;
  101.    if ascnd then
  102.    begin
  103.       Gt_Sign := 1;
  104.       Lt_Sign := -1;
  105.    end
  106.    else
  107.    begin
  108.       Gt_Sign := -1;
  109.       Lt_Sign := 1;
  110.    end;
  111. end;
  112.  
  113. function GS_Sort_Objt.Compare(var s1,s2) : integer;
  114. var
  115.    st1 : string absolute s1;
  116.    st2 : string absolute s2;
  117.    flg : integer;
  118.    eql : boolean;
  119. begin
  120.    eql := st1 = st2;
  121.    Inline(              {Get flag register in flg}
  122.      $9C/                   {  PUSHF           ;Push flag register}
  123.      $59/                   {  POP     CX      ;Get flag register in CX}
  124.      $89/$4E/<flg);         {  MOV     <flg,CX ;Store CX in flg}
  125.    if eql then Compare := 0
  126.       else if (flg and $0080) = 0 then
  127.          Compare := Gt_Sign            {s1 > s2 if sign flag 0}
  128.             else Compare := Lt_Sign;   {s1 < s2 if sign flag 1}
  129. end;
  130.  
  131. {----------------------------------------------------------------------}
  132.  
  133. procedure GS_Sort_Objt.Sort(var tabl; clth : word; icnt : longint);
  134.  
  135.  
  136. { QuickSort algorithm }
  137.  
  138.    procedure qsort(l,r: integer);
  139.    var
  140.       i,j,x             : integer;
  141.       midpoint          : ^buf_type;       { midpoint value }
  142.  
  143.    begin
  144.       i := l;
  145.       j := r;
  146.       x := (l + r) div 2;
  147.       getmem(midpoint,reclen);                { allocate midpoint buffer }
  148.       move(buffer^[x*reclen],midpoint^,reclen);  { get midpoint value }
  149.       repeat
  150.          while Compare(buffer^[i*reclen],midpoint^) < 0 do inc(i);
  151.          while Compare(midpoint^,buffer^[j*reclen]) < 0 do dec(j);
  152.          if i <= j then begin
  153.             GS_Sort_Swap(buffer^[i*reclen],buffer^[j*reclen],reclen);
  154.             inc(i);
  155.             dec(j);
  156.          end;
  157.       until i > j;
  158.       freemem(midpoint,reclen);               { deallocate midpoint buffer }
  159.       if l < j then qsort(l,j);
  160.       if i < r then qsort(i,r);
  161.    end;
  162.  
  163. begin
  164.    buffer := @tabl;
  165.    reclen := clth;
  166.    qsort(0,pred(icnt));
  167. end;
  168.  
  169.  
  170. function  GS_Sort_Objt.Search(key : string; var tabl; clth : word;
  171.                                     icnt : longint) : longint;
  172. var
  173.    l,u,i,j          : integer;
  174.    done             : boolean;
  175.  
  176. begin
  177.    buffer := @tabl;
  178.    l := 0;
  179.    u := icnt;
  180.    done := false;
  181.    while not done do
  182.    begin
  183.       i := (l+u) div 2;                 { compute midpoint of range }
  184.       j := Compare(buffer^[i * clth],key);
  185.       if j=0 then
  186.       begin
  187.          Search := i;
  188.          done := true;
  189.       end else if j<0 then
  190.       begin
  191.          if l=i then
  192.          begin
  193.             Search := -1;
  194.             done := true;
  195.          end else
  196.             l := i;
  197.       end else
  198.       begin
  199.          if u=i then
  200.          begin
  201.             Search := -1;
  202.             done := true;
  203.          end else
  204.             u := i;
  205.       end;
  206.    end;
  207. end;
  208.  
  209.  
  210. end.
  211.